# -*- coding: utf-8 -*-
import os
import pandas as pd
import re
import shutil
import json
from openai import OpenAI
import API_Qianwen
import API_chatGLM
import API_llama
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 初始化 DeepSeek 客户端
client = OpenAI(api_key="sk-b6ae6c7c2ae74c01ae26d7d8ae7a503e", base_url="https://api.deepseek.com")

import json
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def call_deepseek_api_with_example(back, content, example):
    """
    调用 DeepSeek API 进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :param example: 示例
    :return: target, stance, opinion
    """
    # 构造 prompt
    prompt = f"""
这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

示例：
{example}

你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
"""
    try:
        logging.info(f"调用 DeepSeek API，prompt: {prompt}")

        # 调用 DeepSeek API
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system", "content": "你是一个帮助进行立场分析的助手。"},
                {"role": "user", "content": prompt},
            ],
            stream=False
        )

        # 提取返回结果
        result = response.choices[0].message.content.strip()
        logging.info(f"DeepSeek API 返回结果: {result}")

        # 清理结果中的 markdown 语法
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.JSONDecodeError as je:
        logging.error(f"JSON 解析失败: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"调用 DeepSeek API 出错: {e}")
        return None, None, None

def call_deepseek_api_without_example(back, content):
    """
    调用 DeepSeek API 进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    # 构造 prompt
    prompt = f"""
这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
"""
    try:
        logging.info(f"调用 DeepSeek API，prompt: {prompt}")

        # 调用 DeepSeek API
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system", "content": "你是一个帮助进行立场分析的助手。"},
                {"role": "user", "content": prompt},
            ],
            stream=False
        )

        # 提取返回结果
        result = response.choices[0].message.content.strip()
        logging.info(f"DeepSeek API 返回结果: {result}")

        # 清理结果中的 markdown 语法
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.JSONDecodeError as je:
        logging.error(f"JSON 解析失败: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"调用 DeepSeek API 出错: {e}")
        return None, None, None

def call_qw_api_without_example(back, content):
    """
    调用 API 对微博评论进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    prompt = f"""
    这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
    1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
    2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
    3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

    你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
    你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
    """

    try:
        logging.info(f"调用 API，prompt: {prompt}")
        result = API_Qianwen.call_api_my(prompt)
        logging.info(f"API 返回结果: {result}")

        # 清理结果中的无关字符
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.decoder.JSONDecodeError as je:
        logging.error(f"JSON 解析错误: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"发生未知错误: {e}")
        return None, None, None

def call_chatGLM_api_without_example(back, content):
    """
    调用 API 对微博评论进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    prompt = f"""
    这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
    1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
    2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
    3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

    你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
    你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
    """

    try:
        logging.info(f"调用 API，prompt: {prompt}")
        result = call_api_ChatGLM(prompt)
        logging.info(f"API 返回结果: {result}")

        # 清理结果中的无关字符
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.decoder.JSONDecodeError as je:
        logging.error(f"JSON 解析错误: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"发生未知错误: {e}")
        return None, None, None

def call_api_ChatGLM(instruction_content, max_retries=2):
    #url = "http://10.119.130.188:8000/v1/chat/completions"
    url = "http://10.119.130.188:6007"
    for attempt in range(max_retries):
        try:
            payload = {
                "prompt": instruction_content
            }

            response = requests.post(url, json=payload)

            if response.status_code == 200:
                return response.json()['response']
            else:
                print(
                    f"API调用失败，重试 {attempt + 1}/{max_retries}，状态码: {response.status_code}, 响应: {response.text}")

            # 根据不同尝试次数进行截取操作
            if attempt == 0:
                cutoff_length = 1700
            elif attempt == 1:
                cutoff_length = 1600
            else:
                cutoff_length = 1200

            index = instruction_content[cutoff_length:].find('。')
            if index != -1:
                instruction_content = instruction_content[:cutoff_length + index + 1]
            else:
                instruction_content = instruction_content

        except requests.RequestException as e:
            print(f"请求异常，重试 {attempt + 1}/{max_retries}，异常信息: {e}")

    return "Error"

def call_qw_api_with_example(back, content, example):
    """
    调用 API 对微博评论进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    prompt = f"""
    这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
    1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
    2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
    3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

    示例：
    {example}

    你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
    你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
    """

    try:
        logging.info(f"调用 API，prompt: {prompt}")
        result = API_Qianwen.call_api_my(prompt)
        logging.info(f"API 返回结果: {result}")

        # 清理结果中的无关字符
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.decoder.JSONDecodeError as je:
        logging.error(f"JSON 解析错误: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"发生未知错误: {e}")
        return None, None, None

def call_chatGLM_api_without_example(back, content):
    """
    调用 chatGLM API 对微博评论进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    prompt = f"""
    这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
    1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
    2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
    3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

    你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
    你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
    """

    try:
        logging.info(f"调用 API，prompt: {prompt}")
        result = API_chatGLM.call_api(prompt)
        logging.info(f"API 返回结果: {result}")

        # 清理结果中的无关字符
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.decoder.JSONDecodeError as je:
        logging.error(f"JSON 解析错误: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"发生未知错误: {e}")
        return None, None, None

def call_Llama_api_without_example(back, content):
    """
    调用 LLaMa API 对微博评论进行立场分析
    :param back: 背景信息
    :param content: 微博评论内容
    :return: target, stance, opinion
    """
    prompt = f"""
    这件事情的背景是“{back}”。你现在要做的任务是对基于该背景的微博内容或评论进行立场分析。现在给你一段微博评论 content，你需要输出这段评论所指立场的 target 是什么，所持有的观点 opinion 是什么。请注意！有如下要求：
    1. 立场只有 3 种选择：支持、反对、中立。不能输出其他的，比如同情、嘲笑等。
    2. target 指的是这个作者字面上在对谁进行评论？或者说评论的主体/角色。
    3. 观点的意思就是，为什么对这个 target 支持或者反对，表示支持或反对的原因。你不能只输出支持或者反对，你必须输出关于支持或者反对的原因。

    你需要判断下面这段评论的 target、stance、opinion，评论为："{content}"。
    你需要以 JSON 形式输出结果，不能带 markdown 语法，不需要返回无关信息，也不需要解释，只包含 JSON，key 为 target、stance、opinion 这三个。
    """

    try:
        logging.info(f"调用 API，prompt: {prompt}")
        result = API_llama.call_api(prompt)
        logging.info(f"API 返回结果: {result}")

        # 清理结果中的无关字符
        result = result.replace('```', '').replace('json', '').strip()

        # 解析 JSON
        json_obj = json.loads(result)

        # 检查是否包含所需的字段
        if 'target' not in json_obj or 'stance' not in json_obj or 'opinion' not in json_obj:
            logging.error("API 返回结果缺少必要字段")
            return None, None, None

        # 返回解析后的结果
        return json_obj['target'], json_obj['stance'], json_obj['opinion']

    except json.decoder.JSONDecodeError as je:
        logging.error(f"JSON 解析错误: {je}")
        return None, None, None
    except KeyError as ke:
        logging.error(f"JSON 缺少必要字段: {ke}")
        return None, None, None
    except Exception as e:
        logging.error(f"发生未知错误: {e}")
        return None, None, None